﻿using NewLife.Log;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;

namespace AppStart.Common
{
    /// <summary>
    /// 自监控
    /// </summary>
    internal class SelfWatch
    {
        int appId = 0;
        string appFullName = null;
        Process currectProcess = null;
        public SelfWatch(string[] args)
        {

            string id = args[1];
            Assembly currectAssembly = Assembly.GetExecutingAssembly();
            XTrace.WriteLine("Location = " + currectAssembly.Location);
            XTrace.WriteLine("ParentID = " + id);
            int.TryParse(id, out appId);
            currectProcess = Process.GetCurrentProcess();
            appFullName = currectAssembly.Location;
        }
        public void Run()
        {
            //watchThread.Start();
            Watch();
        }

        private void Watch()
        {
            while (true)
            {
                try
                {
                    if (!CheckWatchProcess())
                    {
                        XTrace.WriteLine("restart " + appFullName);
                        StartServer();
                        return;
                    }
                    //if (process == null || process.ProcessName != currectProcess.ProcessName|| process.HasExited)
                    //{
                    //    StartServer();
                    //    return;
                    //}
                    //10秒检测一次
                    Thread.Sleep(10 * 1000);
                }
                catch
                {
                }
            }
        }
        /// <summary>
        /// 检测进程是否存在
        /// </summary>
        /// <returns></returns>
        private bool CheckWatchProcess()
        {
            try
            {
                var currect = Process.GetCurrentProcess();
                var processes = Process.GetProcessesByName(currect.ProcessName);
                //XTrace.WriteLine("check process " + currect.ProcessName);
                int csid = currect.SessionId;
                if (processes != null)
                {
                    for (int i = 0; i < processes.Length; i++)
                    {
                        var item = processes[i];
                        if (item.Id == currect.Id || item.SessionId != csid)
                            continue;
                        if (item.MainModule?.FileName == appFullName)
                            return true;

                    }
                }
            }
            catch (Exception ex)
            {
                XTrace.WriteException(ex);
            }
            return false;
        }
        public static String GetExeName()
        {
            var p = Process.GetCurrentProcess();
            var filename = p.MainModule.FileName;
            //filename = Path.GetFileName(filename);
            filename = filename.Replace(".vshost.", ".");

            return filename;
        }
        protected void StartServer()
        {
            var currect = Process.GetCurrentProcess();
            string fullName = GetExeName();// currect.StartInfo.FileName;
            ProcessStartInfo startInfo = new ProcessStartInfo(fullName, "-start");
            startInfo.WorkingDirectory = Path.GetDirectoryName(fullName);
            startInfo.UseShellExecute = true;
            XTrace.WriteLine("restart " + fullName);
            Process.Start(startInfo);
        }
        static int watchAppId = 0;
        public static void StartWatch()
        {
            var currect = Process.GetCurrentProcess();
            string fullName = GetExeName();// currect.StartInfo.FileName;
            ProcessStartInfo startInfo = new ProcessStartInfo(fullName, "-w " + currect.Id);
            startInfo.WorkingDirectory = Path.GetDirectoryName(fullName);
            startInfo.UseShellExecute = true;
            watchAppId = Process.Start(startInfo).Id;
            XTrace.WriteLine("watch id = " + watchAppId);
        }
        public static void StopWatch()
        {
            try
            {
                if (watchAppId < 1)
                    return;
                var currect = Process.GetCurrentProcess();
                string currectFileName = GetExeName();
                int csid = currect.SessionId;
                XTrace.WriteLine("Currect process sid:" + currect.SessionId);
                var processes = Process.GetProcessesByName(currect.ProcessName);
                if (processes != null)
                {
                    for (int i = 0; i < processes.Length; i++)
                    {
                        var item = processes[i];
                        if (item.Id == currect.Id)
                            continue;
                        XTrace.WriteLine("other process:" + item.Id + " " + item.MainModule?.FileName);
                        XTrace.WriteLine("other process sid:" + item.SessionId);
                        if (item.SessionId != csid)
                            continue;
                        if (item.MainModule?.FileName == currectFileName)
                            item.Kill();
                    }
                }

                var process = Process.GetProcessById(watchAppId);
                if (process != null && process.ProcessName == currect.ProcessName)
                {
                    process.Kill();
                }
            }
            catch { }
        }
    }
}
